home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Almathera Ten Pack 1: Comms & Networking
/
Almathera Ten on Ten - Disc 1: Comms & Networking.iso
/
tools
/
www
/
aminet2ag
/
aminet2ag.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-04-21
|
20KB
|
806 lines
/*
**
** $VER: Aminet2AG.c 2.0 (06.04.95)
**
** Convert AminNet INDEX files in AmigaGuide© documents.
**
** Copyrigth (C) 1995 José Roberto González Rocha.
**
**
**
** Link without any C header (c.o ...)
** Fully resident and reentrant (pure).
**
*/
/*********************************************************************************/
#include <exec/types.h>
#include <exec/nodes.h>
#include <exec/lists.h>
#include <exec/execbase.h>
#include <exec/memory.h>
#include <dos/dos.h>
#include <dos/dosextens.h>
#include <dos/rdargs.h>
#include <dos/stdio.h>
#include <workbench/startup.h>
#include <clib/dos_protos.h>
#include <clib/exec_protos.h>
#include <clib/utility_protos.h>
#include <pragmas/dos_pragmas.h>
#include <pragmas/exec_pragmas.h>
#include <pragmas/utility_pragmas.h>
/* Shared data and libs */
struct GlobalData
{
struct ExecBase *gd_SysBase;
struct Library *gd_DOSBase;
struct Library *gd_UtilityBase;
struct Process *gd_Process;
struct WBStartup *gd_wbMsg;
LONG gd_failureLevel;
LONG gd_failureCode;
ULONG mem;
LONG ArgArray[11];
BPTR gd_In; /* Source INDEX file. */
BPTR gd_Out; /* Destination AmigaGuidec doc */
UBYTE gd_string[100];
WORD total_pending;
WORD root_count; /* total file count */
WORD root_dircount; /* number of dirs. */
WORD root_subcount; /* number of subdirs. */
LONG root_size; /* total size (incl. all dirs) */
BOOL root_ignore; /* ignore same file size. */
WORD root_pending; /* filecount of files w/o dirs. */
struct Dir *root_firstdir; /* linked list head. */
struct Dir *root_lastdir; /* link to the last dir */
};
#define SysBase gd->gd_SysBase
#define DOSBase gd->gd_DOSBase
#define UtilityBase gd->gd_UtilityBase
/* SubDir Nodes data */
struct SubDir
{
struct SubDir *sub_next; /* link */
char sub_name[6]; /* name of this subdir. */
WORD sub_count; /* file count in this subdir. */
LONG sub_size; /* total size of this subdir. */
BOOL sub_ignore; /* ignore same filesize. */
};
/* Dir Nodes data */
struct Dir
{
struct Dir *dir_next; /* link */
char dir_name[6]; /* name of this dir. */
WORD dir_subcount; /* subdir count of this dir. */
WORD dir_count; /* total file count of this dir */
LONG dir_size; /* total size of this subdir. */
BOOL dir_ignore; /* ignore same filesize */
WORD dir_pending; /* file count of files w/o sub */
struct SubDir *dir_firstsub; /* linked list head. */
struct SubDir *dir_lastsub; /* link to the last subdir. */
};
#define isnum(a) ((a >= '0') && (a <= '9'))
/*
* Function prototipes
*/
BOOL PassOne(struct GlobalData *gd, ULONG Flags);
BOOL PassTwo(struct GlobalData *gd, ULONG Flags);
BOOL PassThree(struct GlobalData *gd, ULONG Flags);
BOOL CheckAbort(struct GlobalData *gd);
VOID PrintSize(struct GlobalData *gd, LONG size, BOOL ignore);
/*
* Main funcion.
* Don't use argc/argv, so why use standard main()?.
*/
LONG main(VOID)
{
/* Version string */
char VersionString[] = "$VER: Aminet2AG 2.0 (06.04.95)";
/* Credits */
char CopyRigthString[] = "Copyright (c) 1995 José Roberto González Rocha";
/* Command template */
char Template[] = "FROMFILE/A,TOFILE/A,DC=DIRCOL/K/N,"
"NT=NOTOTAL/S,NH=NOHEAD/S,NL=NOTITLE/S,"
"TR=TITLEROW/K/N,NS=NOSTATS/S,SC=SIZECOL/K/N,"
"P=PLAIN/S,V=VERBOSE/S";
struct GlobalData gdd = {NULL};
struct GlobalData *gd = &gdd;
/* Returned object from template parsing */
struct RDArgs *rdargs;
/* Position of the argument in the array */
#define FROM_FILE 0
#define TO_FILE 1
#define DIRCOL 2
#define NOTOTAL 3
#define NOHEAD 4
#define NOTITLE 5
#define TITLEROW 6
#define NOSTATS 7
#define SIZECOL 8
#define PLAIN 9
#define VERBOSE 10
/* Quick form of options, used for and'ing and or'ing */
REGISTER ULONG Flags = 0L;
#define F_NODIR (1L << 0)
#define F_NOSUB (1L << 1)
#define F_VERBOSE (1L << 2)
#define F_NOSTATS (1L << 3)
#define F_NOTITLE (1L << 4)
#define F_NOHEAD (1L << 5)
#define F_NOTOTAL (1L << 6)
#define F_FIXDIR (1L << 7)
#define F_FIXSUB (1L << 8)
#define F_POINT (1L << 9)
#define F_NOSIZE (1L << 10)
gdd.gd_SysBase = *((struct ExecBase **) 4L);
gdd.gd_failureLevel = RETURN_FAIL;
gdd.gd_Process = (struct Process *) SysBase->ThisTask;
/* We only run from CLI */
if(gdd.gd_Process->pr_CLI)
{
#ifdef _M68020
/* Make sure we are running with a 68020+ CPU */
if (gdd.gd_SysBase->AttnFlags & AFF_68020)
{
#endif
/* Open the ROM libraries */
if(gdd.gd_DOSBase = OpenLibrary ("dos.library", 37L))
{
if(gdd.gd_UtilityBase = OpenLibrary ("utility.library", 37L))
{
/* Our process. Really necessary? */
gdd.gd_Process = (struct Process *) FindTask (NULL);
if(rdargs = ReadArgs( Template, gdd.ArgArray, NULL))
{
if (gdd.gd_In = Open((STRPTR)(gdd.ArgArray[FROM_FILE]), MODE_OLDFILE))
{
if (gdd.gd_Out = Open((STRPTR)(gdd.ArgArray[TO_FILE]), MODE_NEWFILE))
{
/* Options processing */
if(gdd.ArgArray[DIRCOL] == 0L)
gdd.ArgArray[DIRCOL] = 19L;
else
gdd.ArgArray[DIRCOL] = *((LONG *)(gdd.ArgArray[DIRCOL]));
if(gdd.ArgArray[TITLEROW] == 0L)
gdd.ArgArray[TITLEROW] = 3L;
else
gdd.ArgArray[TITLEROW] = *((LONG *)(gdd.ArgArray[TITLEROW]));
if(gdd.ArgArray[SIZECOL] == 0L)
gdd.ArgArray[SIZECOL] = 30L;
else
gdd.ArgArray[SIZECOL] = *((LONG *)(gdd.ArgArray[SIZECOL]));
if(gdd.ArgArray[VERBOSE])
Flags |= F_VERBOSE;
if(gdd.ArgArray[PLAIN]) /* Overrides all the other flags. */
{
Flags |= F_NOHEAD | F_NOTITLE | F_NOSTATS | F_NOTOTAL;
}
else
{
if(gdd.ArgArray[NOHEAD])
Flags |= F_NOHEAD;
if(gdd.ArgArray[NOTITLE])
Flags |= F_NOTITLE;
if(gdd.ArgArray[NOSTATS])
/* If we don't want stats, why put header? */
Flags |= F_NOSTATS | F_NOHEAD;
if(gdd.ArgArray[NOTOTAL])
Flags |= F_NOTOTAL;
}
if((Flags & (F_NOSTATS | F_NOTOTAL)) == (F_NOSTATS | F_NOTOTAL))
Flags |= F_NOSIZE;
if(!CheckAbort(gd))
{
if(PassOne(gd, Flags))
if(PassTwo(gd, Flags))
if(PassThree(gd, Flags))
{
gdd.gd_failureLevel = RETURN_OK;
if(Flags & F_VERBOSE)
{
Printf("\n\n\nAll Done!\n");
Printf("\nFounds: %5ld dirs, %5ld subdirs, %5ld files, %5ld KBytes\n",
gdd.root_dircount, gdd.root_subcount,
gdd.root_count, gdd.root_size);
}
}
{
struct Dir *DirNode,*DirNode2;
struct SubDir *SubDirNode,*SubDirNode2;
if(Flags & F_VERBOSE)
Printf( "\nUtilized %ld bytes\n", gdd.mem);
/* Dealocates all memory. */
gdd.mem = 0;
DirNode2 = gd->root_firstdir;
while((DirNode = DirNode2) != NULL)
{
SubDirNode2 = DirNode->dir_firstsub;
while((SubDirNode = SubDirNode2) != NULL)
{
SubDirNode2 = SubDirNode->sub_next;
FreeMem(SubDirNode, sizeof(struct SubDir));
gdd.mem += sizeof(struct SubDir);
}
DirNode2 = DirNode->dir_next;
FreeMem(DirNode, sizeof(struct Dir));
gdd.mem += sizeof(struct Dir);
}
if(Flags & F_VERBOSE)
Printf("Dealocated %ld bytes\n\n", gdd.mem);
}
}
Close(gdd.gd_Out);
}
else
{
Printf("***Error Opening Destination File \'%s\'\n", gdd.ArgArray[FROM_FILE]);
gdd.gd_failureCode = 201;
}
Close(gdd.gd_In);
}
else
{
Printf("***Error Opening Source File \'%s\'\n", gdd.ArgArray[FROM_FILE]);
gdd.gd_failureCode = 201;
}
FreeArgs(rdargs);
}
else
{
if(!CheckAbort(gd))
{
Printf("%s\n%s\n", VersionString + 6, CopyRigthString);
}
else
gdd.gd_failureCode = 200;
}
CloseLibrary(gdd.gd_UtilityBase);
}
else
gdd.gd_failureCode = 21;
CloseLibrary(gdd.gd_DOSBase);
}
else
gdd.gd_failureCode = 20;
#ifdef _M68020
}
else
gdd.gd_failureCode = 10;
#endif
}
/* If running from WorkBench do nothing */
else
{
gdd.gd_failureCode = 1;
WaitPort (&(gdd.gd_Process->pr_MsgPort));
gdd.gd_wbMsg = (struct WBStartup *) GetMsg (&gdd.gd_Process->pr_MsgPort);
Forbid();
ReplyMsg((struct Message *)gdd.gd_wbMsg);
}
gdd.gd_Process->pr_Result2 = gdd.gd_failureCode;
return(gdd.gd_failureLevel);
}
/*
*
*
*/
BOOL PassOne(struct GlobalData *gd, ULONG Flags)
{
REGISTER struct Dir *DirNode;
REGISTER struct SubDir *SubDirNode;
REGISTER WORD i = 0;
char *dir;
char *subdir;
char *olddir = "";
char *oldsubdir = "";
LONG filesize;
FPrintf(gd->gd_Out,"@database \"AMINET\"\n");
if(Flags & F_VERBOSE)
{
Printf("
Pass One
\n");
}
DirNode = NULL;
SubDirNode = NULL;
FPrintf(gd->gd_Out,"@NODE Main \"AmiNet Root Directory\"\n");
FGets(gd->gd_In, gd->gd_string, 100);
while(gd->gd_string[0] == '|')
{
if(!(Flags & F_NOTITLE))
{
if(i < gd->ArgArray[TITLEROW])
{
FPuts(gd->gd_Out, gd->gd_string+1);
i++;
}
}
FGets(gd->gd_In, gd->gd_string, 100);
}
if(!(Flags & F_NOTITLE))
FPuts(gd->gd_Out, "\n");
do
{
if(!(Flags & F_NOSIZE))
{
if(gd->gd_string[gd->ArgArray[SIZECOL] + 3] == '?')
filesize = -1;
else
{
Flags &= ~F_POINT;
filesize = 0;
for(i = gd->ArgArray[SIZECOL]; i < gd->ArgArray[SIZECOL] + 3; i++)
if(isnum(gd->gd_string[i]))
filesize = SMult32(filesize, 10) + (gd->gd_string[i] - '0');
else if(gd->gd_string[i] == '.')
Flags |= F_POINT;
if(gd->gd_string[i] == 'M')
{
filesize <<= 10;
if(Flags & F_POINT)
filesize = SDivMod32(filesize, 10);
}
}
}
dir = gd->gd_string + gd->ArgArray[DIRCOL];
dir[10] = 0;
subdir = FilePart(dir);
if(dir == subdir)
Flags |= F_NOSUB;
else
Flags &= ~F_NOSUB;
if(dir[0] == ' ')
Flags |= F_NODIR;
else
Flags &= ~F_NODIR;
if(!(Flags & F_NODIR))
{
if(Flags & F_NOSUB)
{
while(subdir[0] != ' ')
subdir++;
subdir[0] = 0;
}
else
*(subdir-1) = 0;
if(Strnicmp(olddir, dir, 5L))
{
if(DirNode != NULL)
{
FPrintf(gd->gd_Out,"@{\" %-5s \" link %s}", DirNode->dir_name, DirNode->dir_name);
if(!(Flags & F_NOSTATS))
{
FPrintf(gd->gd_Out, " %5ld %5ld " , DirNode->dir_subcount, DirNode->dir_count);
PrintSize(gd, DirNode->dir_size, DirNode->dir_ignore);
}
else
FPuts(gd->gd_Out, "\n");
}
else
if(!(Flags & F_NOHEAD))
FPuts(gd->gd_Out, " subdirs files size\n"
"-------------------------------------------------\n");
if( (DirNode = (struct Dir *)AllocMem(sizeof(struct Dir), MEMF_CLEAR)) == NULL)
{
gd->gd_failureCode = 100;
return(FALSE);
}
gd->mem += sizeof(struct Dir);
for(i = 0; dir[i], i < 5; i ++)
DirNode->dir_name[i] = dir[i];
DirNode->dir_name[i] =0;
if(gd->root_firstdir != NULL)
gd->root_lastdir->dir_next = DirNode;
else
gd->root_firstdir = DirNode;
gd->root_lastdir = DirNode;
gd->root_dircount++;
olddir = DirNode->dir_name;
oldsubdir = "";
}
DirNode->dir_count++;
if(filesize != -1)
DirNode->dir_size += filesize;
else
DirNode->dir_ignore = TRUE;
if(!(Flags & F_NOSUB))
{
if(Strnicmp(oldsubdir, subdir, 5))
{
if(CheckAbort(gd))
return(FALSE);
if((SubDirNode = (struct SubDir *)AllocMem(sizeof(struct SubDir), MEMF_CLEAR)) == NULL)
{
gd->gd_failureCode = 100;
return(FALSE);
}
gd->mem += sizeof(struct SubDir);
for(i = 0; dir[i], i < 5; i ++)
SubDirNode->sub_name[i] = subdir[i];
SubDirNode->sub_name[i] =0;
if(DirNode->dir_firstsub != NULL)
DirNode->dir_lastsub->sub_next = SubDirNode;
else
DirNode->dir_firstsub = SubDirNode;
DirNode->dir_lastsub = SubDirNode;
DirNode->dir_subcount++;
gd->root_subcount++;
oldsubdir = SubDirNode->sub_name;
if(Flags & F_VERBOSE)
{
Printf("Found Dir : %s \n"
"Found Sub-Dir: %s M\r", DirNode->dir_name, SubDirNode->sub_name);
}
}
SubDirNode->sub_count++;
if(filesize != -1)
SubDirNode->sub_size += filesize;
else
SubDirNode->sub_ignore = TRUE;
}
else
{
Flags |= F_FIXSUB;
DirNode->dir_pending++;
gd->total_pending++;
}
}
else
{
Flags |= F_FIXDIR;
gd->root_pending++;
gd->total_pending++;
dir[10] = ' ';
FPuts(gd->gd_Out, gd->gd_string);
}
if(filesize != -1)
gd->root_size += filesize;
else
gd->root_ignore = TRUE;
gd->root_count++;
}while(FGets(gd->gd_In, gd->gd_string, 100));
if(DirNode != NULL)
{
FPrintf(gd->gd_Out,"@{\" %-5s \" link %s}", DirNode->dir_name, DirNode->dir_name);
if(!(Flags & F_NOSTATS))
{
FPrintf(gd->gd_Out, " %5ld %5ld ", DirNode->dir_subcount, DirNode->dir_count);
PrintSize(gd, DirNode->dir_size, DirNode->dir_ignore);
}
else
FPuts(gd->gd_Out, "\n");
}
if(!(Flags & F_NOTOTAL))
{
FPrintf(gd->gd_Out, "\nTotal: %ld dirs, %ld subdirs, %ld files, size ", gd->root_dircount, gd->root_subcount, gd->root_count);
PrintSize(gd, gd->root_size, gd->root_ignore);
}
FPuts(gd->gd_Out, "@ENDNODE\n\n");
if( gd->total_pending && (Flags & F_VERBOSE))
{
Printf("\n\nFound(s) %ld file(s) without ", gd->total_pending);
if(Flags & F_FIXDIR)
{
Printf("directory");
if(Flags & F_FIXSUB)
Printf(" and/or ");
}
if(Flags & F_FIXSUB)
Printf("subdirectory");
if(gd->root_pending)
Printf(".\nAdded files to root directory (%ld)", gd->root_pending);
Printf(".\n\nEntering FIX mode (Pass Two may take a while).M\r");
}
return(TRUE);
}
/*
*
*
*/
BOOL PassTwo(struct GlobalData *gd, ULONG Flags)
{
REGISTER struct Dir *DirNode;
REGISTER struct SubDir *SubDirNode;
REGISTER WORD i;
if(Flags & F_VERBOSE)
Printf("\n\n\n
Pass Two
\n");
if(gd->total_pending)
{
Seek(gd->gd_In, 0, OFFSET_BEGINNING);
FGets(gd->gd_In, gd->gd_string, 80);
/* Skip index header. */
while(gd->gd_string[0] == '|')
FGets(gd->gd_In, gd->gd_string, 100);
if((Flags & F_VERBOSE) && gd->root_pending)
Printf("Skipping root directory files (%ld)\n", gd->root_pending);
gd->total_pending -= gd->root_pending;
/* Skip files w/o dir/subdir. */
for(i = 0; i < gd->root_pending; i++)
FGets(gd->gd_In, gd->gd_string,100);
}
DirNode = gd->root_firstdir;
while(DirNode != NULL)
{
if(Flags & F_VERBOSE)
Printf("Creating Node: %s M\n",DirNode->dir_name);
FPrintf(gd->gd_Out, "@NODE %s \"%s Directory\"\n\n", DirNode->dir_name,DirNode->dir_name);
if(gd->total_pending)
{
if((Flags & F_VERBOSE) && DirNode->dir_pending)
Printf("Adding directory \"%s\" files (%ld)\n", DirNode->dir_name, DirNode->dir_pending);
gd->total_pending -= DirNode->dir_pending;
for(i = 0; i < DirNode->dir_pending; i++)
{
FPuts(gd->gd_Out, gd->gd_string);
FGets(gd->gd_In, gd->gd_string, 100);
}
for(; i < DirNode->dir_count; i++)
FGets(gd->gd_In, gd->gd_string, 100);
}
if (CheckAbort(gd))
return(FALSE);
if(!(Flags & F_NOHEAD))
FPuts(gd->gd_Out, " files size\n"
"-------------------------------------------------\n");
SubDirNode = DirNode->dir_firstsub;
while(SubDirNode != NULL)
{
FPrintf(gd->gd_Out, "@{\" %-5s \" link %s-%s}", SubDirNode->sub_name, DirNode->dir_name, SubDirNode->sub_name);
if(!(Flags & F_NOSTATS))
{
FPrintf(gd->gd_Out, " %5ld ", SubDirNode->sub_count);
PrintSize(gd, SubDirNode->sub_size, SubDirNode->sub_ignore);
}
else
FPuts(gd->gd_Out, "\n");
SubDirNode = SubDirNode->sub_next;
}
if(!(Flags & F_NOTOTAL))
{
FPrintf(gd->gd_Out, "\nTotal: %5ld subdirs, %5ld files, size ", DirNode->dir_subcount, DirNode->dir_count);
PrintSize(gd, DirNode->dir_size, DirNode->dir_ignore);
}
FPuts(gd->gd_Out, "@ENDNODE\n\n");
DirNode = DirNode->dir_next;
}
return(TRUE);
}
/*
*
*
*/
BOOL PassThree(struct GlobalData *gd, ULONG Flags)
{
REGISTER struct Dir *DirNode;
REGISTER struct SubDir *SubDirNode;
REGISTER WORD i;
if(Flags & F_VERBOSE)
Printf("\n\n
Pass Three
\n");
Seek(gd->gd_In, 0, OFFSET_BEGINNING);
FGets(gd->gd_In, gd->gd_string, 80);
/* Skip index header */
while(gd->gd_string[0] == '|')
FGets(gd->gd_In, gd->gd_string, 100);
if((Flags & F_VERBOSE) && gd->root_pending)
Printf("Skipping root directory files (%ld)\n", gd->root_pending);
/* Skip files w/o dir/subdir */
for(i = 0; i < gd->root_pending; i++)
FGets(gd->gd_In, gd->gd_string,100);
DirNode = gd->root_firstdir;
while(DirNode != NULL)
{
if((Flags & F_VERBOSE) && DirNode->dir_pending)
Printf("Skipping directory \"%s\" files (%ld)\n", DirNode->dir_name, DirNode->dir_pending);
/* Skip files with dir and w/o subdir */
for(i = 0; i < DirNode->dir_pending; i++)
FGets(gd->gd_In, gd->gd_string, 100);
SubDirNode = DirNode->dir_firstsub;
while(SubDirNode != NULL)
{
if(Flags & F_VERBOSE)
{
Printf("Working on Node : %s \n"
"Creating Sub-Dir: %s M\r", DirNode->dir_name, SubDirNode->sub_name);
}
if(CheckAbort(gd))
return(FALSE);
FPrintf(gd->gd_Out, "@NODE %s-%s \"%s/%s SubDirectory\"\n\n", DirNode->dir_name, SubDirNode->sub_name, DirNode->dir_name, SubDirNode->sub_name);
for(i = 0; i < SubDirNode->sub_count; i++)
{
FPuts(gd->gd_Out, gd->gd_string);
FGets(gd->gd_In, gd->gd_string, 100);
}
if(!(Flags & F_NOTOTAL))
{
FPrintf(gd->gd_Out, "\nTotal: %5ld files, size ", SubDirNode->sub_count);
PrintSize(gd, SubDirNode->sub_size, SubDirNode->sub_ignore);
}
FPuts(gd->gd_Out, "@ENDNODE\n\n");
SubDirNode = SubDirNode->sub_next;
}
DirNode = DirNode->dir_next;
}
return(TRUE);
}
/*
* Function to check for CTRL-C break.
*/
BOOL CheckAbort(struct GlobalData *gd)
{
if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C)
{
Printf("\n\n***User Abort\n");
gd->gd_failureCode = 200;
return(TRUE);
}
return(FALSE);
}
/*
* Print (write to file) the size of an item (root, dir, subdir, file).
* Scale format in order to make it smaller and more readable
* (1024KByte-> 1M, 1024MByte -> 1GByte)
*/
VOID PrintSize(struct GlobalData *gd, LONG size, BOOL ignore)
{
/* Exact or aproximate size ? */
if(ignore)
FPutC(gd->gd_Out, '>');
else
FPutC(gd->gd_Out, '=');
if(!(size & 0xFFFFFC00)) /* Size < 1MByte (1024) */
FPrintf(gd->gd_Out, "%5ldK\n", size);
else if(!(size & 0xFFF00000)) /* Size < 1Gbyte (1048576) */
FPrintf(gd->gd_Out, "%3ld.%01ldM\n", size >> 10, SDivMod32((size & 0x000003FF), 100));
else
FPrintf(gd->gd_Out, "%3ld.%-02ldG\n", size >> 20, SDivMod32((size & 0x000FFFFF), 10000));
}